home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / Python 133 SRC / Demo / www / rtlib.py < prev    next >
Text File  |  1996-03-12  |  6KB  |  243 lines

  1. # Parser for MIME Richtext.
  2.  
  3. # The official definition of Richtext prescribes a different handling
  4. # of invalid input than is done by our SGML parser base class.
  5. # However, for valid richtext the interpretation will be correct.
  6. # (Possibly we could make the behaviour of the SGML parser more
  7. # flexible, e.g. define a regular expression that recognizes tags?)
  8.  
  9.  
  10. import regex
  11. import string
  12. import sgmllib
  13.  
  14.  
  15. wordprog = regex.compile('[^ \t\n]*')
  16. spaceprog = regex.compile('[ \t\n]*')
  17.  
  18.  
  19. class FormattingParser(sgmllib.SGMLParser):
  20.  
  21.     entitydefs = {}            # Richtext doesn't use entities
  22.  
  23.     def __init__(self, formatter, stylesheet):
  24.         sgmllib.SGMLParser.__init__(self)
  25.         self.fmt = formatter
  26.         self.stl = stylesheet
  27.         self.savetext = None
  28.         self.skip = 0
  29.         self.comment = 0
  30.         self.font = 'roman'
  31.         self.size = 0
  32.         self.just = 'l'
  33.         self.leftindent = 0
  34.         self.rightindent = 0
  35.         self.fontstack = []
  36.         self.sizestack = []
  37.         self.juststack = []
  38.         self.leftstack = []
  39.         self.rightstack = []
  40.  
  41.     def handle_text(self, text):
  42.         if self.skip > 0: return
  43.         if self.savetext is not None:
  44.             self.savetext = self.savetext + text
  45.             return
  46.         i = 0
  47.         n = len(text)
  48.         while i < n:
  49.             j = i + wordprog.match(text, i)
  50.             word = text[i:j]
  51.             i = j + spaceprog.match(text, j)
  52.             self.fmt.addword(word, i-j)
  53.  
  54.     handle_literal = handle_text    # XXX not used anyway???
  55.  
  56.     def passfont(self):
  57.         self.fmt.setfont(self.stl.makefont(self.font, self.size))
  58.  
  59.     def pushfont(self, font):
  60.         self.fontstack.append(self.font)
  61.         self.font = font
  62.         self.passfont()
  63.  
  64.     def popfont(self):
  65.         self.font = self.fontstack[-1]
  66.         del self.fontstack[-1]
  67.         self.passfont()
  68.  
  69.     def pushsize(self, size):
  70.         self.sizestack.append(self.size)
  71.         self.size = size
  72.         self.passfont()
  73.  
  74.     def popsize(self):
  75.         self.size = self.sizestack[-1]
  76.         del self.sizestack[-1]
  77.         self.passfont()
  78.  
  79.     def pushjust(self, just):
  80.         self.juststack.append(self.just)
  81.         self.just = just
  82.         self.fmt.setjust(self.just)
  83.  
  84.     def popjust(self):
  85.         self.just = self.juststack[-1]
  86.         del self.juststack[-1]
  87.         self.fmt.setjust(self.just)
  88.  
  89.     def pushleft(self, leftindent):
  90.         self.leftstack.append(self.leftindent)
  91.         self.leftindent = leftindent
  92.         self.fmt.setleftindent(self.leftindent)
  93.  
  94.     def popleft(self):
  95.         self.leftindent = self.leftstack[-1]
  96.         del self.leftstack[-1]
  97.         self.fmt.setleftindent(self.leftindent)
  98.  
  99.     def pushright(self, rightindent):
  100.         self.rightstack.append(self.rightindent)
  101.         self.rightindent = rightindent
  102.         self.fmt.setrightindent(self.rightindent)
  103.  
  104.     def popright(self):
  105.         self.rightindent = self.rightstack[-1]
  106.         del self.rightstack[-1]
  107.         self.fmt.setrightindent(self.rightindent)
  108.  
  109.     # Set nesting literal end pattern
  110.     def setnestingliteral(self, tag):
  111.         re = '</?'
  112.         for c in tag:
  113.             c, C = string.lower(c), string.upper(c)
  114.             if c == C:
  115.                 if c in '\\.*+?[^$':
  116.                     c = '\\' + c
  117.                 re = re + c
  118.             else:
  119.                 re = re + '[' + c + C + ']'
  120.         re = re + '>'
  121.         self.litprog = regex.compile(re)
  122.  
  123.     def do_lt(self, attrs): self.handle_text('<')
  124.     def do_nl(self, attrs): self.fmt.flush()
  125.     def do_np(self, attrs): self.fmt.flush() ### What else?
  126.  
  127.     def bgn_comment(self, attrs):
  128.         self.comment = self.comment + 1
  129.         self.skip = self.skip + 1
  130.         self.setnestingliteral('comment')
  131.     def end_comment(self, attrs):
  132.         self.skip = self.skip - 1
  133.         self.comment = self.comment - 1
  134.         if self.comment > 0:
  135.             self.setnestingliteral('comment')
  136.  
  137.     def ignore_bgn(self, attrs): self.skip = self.skip + 1
  138.     def ignore_end(self, attrs): self.skip = self.skip - 1
  139.  
  140.     def bgn_bold(self, attrs): self.pushfont('bold')
  141.     def end_bold(self, attrs): self.popfont()
  142.  
  143.     def bgn_italic(self, attrs): self.pushfont('italic')
  144.     def end_italic(self, attrs): self.popfont()
  145.  
  146.     def bgn_fixed(self, attrs): self.pushfont('fixed')
  147.     def end_fixed(self, attrs): self.popfont()
  148.  
  149.     def bgn_smaller(self, attrs): self.pushsize(self.size - 1)
  150.     def end_smaller(self, attrs): self.popsize()
  151.  
  152.     def bgn_bigger(self, attrs): self.pushsize(self.size + 1)
  153.     def end_bigger(self, attrs): self.popsize()
  154.  
  155.     def bgn_underline(self, attrs): self.pushfont(self.font + ' underline')
  156.     def end_underline(self, attrs): self.popfont()
  157.  
  158.     def bgn_center(self, attrs): self.pushjust('c')
  159.     def end_center(self, attrs): self.popjust()
  160.  
  161.     def bgn_flushleft(self, attrs): self.pushjust('l')
  162.     def end_flushleft(self, attrs): self.popjust()
  163.  
  164.     def bgn_flushright(self, attrs): self.pushjust('r')
  165.     def end_flushright(self, attrs): self.popjust()
  166.  
  167.     def bgn_indent(self, attrs):
  168.         self.pushleft(self.leftindent + self.stl.indentstep)
  169.     def end_indent(self, attrs): self.popleft()
  170.  
  171.     def bgn_rightindent(self, attrs):
  172.         self.pushright(self.rightindent + self.stl.indentstep)
  173.     def end_rightindent(self, attrs): self.popright()
  174.  
  175.     def bgn_outdent(self, attrs):
  176.         self.pushleft(self.leftindent - self.stl.indentstep)
  177.     def end_outdent(self, attrs): self.popleft()
  178.  
  179.     def bgn_rightoutdent(self, attrs):
  180.         self.pushright(self.rightindent - self.stl.indentstep)
  181.     def end_rightoutdent(self, attrs): self.popright()
  182.  
  183.     def bgn_subscript(self, attrs): self.pushfont(self.font + ' subscript')
  184.     def end_subscript(self, attrs): self.popfont()
  185.  
  186.     def bgn_superscript(self, attrs):
  187.         self.pushfont(self.font + ' superscript')
  188.     def end_superscript(self, attrs): self.popfont()
  189.  
  190.     bgn_heading = ignore_bgn
  191.     end_heading = ignore_end
  192.  
  193.     bgn_footing = ignore_bgn
  194.     end_footing = ignore_end
  195.  
  196.     def bgn_excerpt(self, attrs):
  197.         self.fmt.flush()
  198.         self.pushfont('fixed')
  199.     def end_excerpt(self, attrs):
  200.         self.popfont()
  201.         self.fmt.flush()
  202.  
  203.     def bgn_signature(self, attrs): self.fmt.flush()
  204.     def end_signature(self, attrs): self.fmt.flush()
  205.  
  206.     def bgn_paragraph(self, attrs): self.fmt.flush()
  207.     def end_paragraph(self, attrs): self.fmt.flush()
  208.  
  209.  
  210. class NullStylesheet:
  211.  
  212.     indentstep = 4
  213.  
  214.     def makefont(font, size):
  215.         if not font: f = 'r'
  216.         else: f = font[0]
  217.         if size > 0: f = string.upper(f)
  218.         return f
  219.  
  220.  
  221. def test():
  222.     import sys
  223.     import fmt
  224.     import time
  225.     if sys.argv[1:]: file = sys.argv[1]
  226.     else: file = 'demo.rich'
  227.     data = open(file, 'r').read()
  228.     t0 = time.time()
  229.     if sys.argv[2:]:
  230.         fmtr = fmt.NullFormatter()
  231.     else:
  232.         fmtr = fmt.FunnyFormatter(sys.stdout, 79)
  233.     p = FormattingParser(fmtr, NullStylesheet)
  234.     p.feed(data)
  235.     p.close()
  236.     fmtr.flush()
  237.     t1 = time.time()
  238.     print
  239.     print '*** Formatting time:', round(t1-t0, 3), 'seconds.'
  240.  
  241.  
  242. test()
  243.